/*
	J-Bird net/sourceforge/jbird/io/DelimitedExtractor.java

        Copyright (C) 2001-2007 Dick Repasky
	drepasky@users.sourceforge.net

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License 
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	General Public License for more details.

	You should have received a copy of the GNU General Public 
	License along with this program; if not, write to the Free Software 
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*/
package net.sourceforge.jbird.io;

import java.io.IOException;
import java.io.Reader;

import java.util.ArrayList;

/**
  * A class that can extract data from a delimited file into a
  * matrix represented as a rectangular ArrayList of ArrayLists.
  * <p>
  * Instantiate and configure as you would DelimitedTokenizer.
  * Then, call the extractRectangularData method.  Not that it is
  * acceptable to read some rows from a Reader using methods of
  * DelimitedTokenizer and then to read the remaining rows into
  * a matrix using extractRectangularData.
  * @author Dick Repasky
  * @since J-Bird 0.4.1
*/

public class DelimitedExtractor extends DelimitedTokenizer {

		/** True if all rows should have the same number of columns. */
	protected boolean build_square = true;

	protected int minlength = -1;
	protected int maxlength = -1;

	public DelimitedExtractor(Reader reader) {
		super(reader);
	}

		/**
		  * Read data remaing in the reader into a matrix
		  * that is represented as an ArrayList of ArrayLists
		  * in which all rows have the same number of columns.
		*/

	public final ArrayList extractRectangularData() throws IOException {
		ArrayList answer = new ArrayList(250);
		Object[] aline = getLineObjects();
		int minbuilt = aline.length;
		while(aline != null) {
			int linelen = aline.length;
			if (linelen < minlength && minlength < 0) {
				minlength = linelen;
			}
			if (linelen > maxlength) {
				maxlength = linelen;
			}
			ArrayList linelist = new ArrayList(linelen);
			int idx;
			for (idx = 0; idx < linelen; idx ++) {
				linelist.add(aline[idx]);
			}
			fillToMax(linelist);
			answer.add(linelist);
			aline = getLineObjects();
		}
		fillAllToMax(answer);
		return answer;
	}

	///////////////////////// private below //////////////////////////////

		/** 
		  * Fill all rows to be the length of the longest row.
		  * It is OK to stop once the maximum is hit because
		  * of the manner in which rows are constructed.
		*/
		 
	private final void fillAllToMax(ArrayList al) {
		int allen = al.size();
		for (int idx = 0; idx < allen; idx ++) {
			ArrayList arow = (ArrayList)al.get(idx);
			if (arow.size() < maxlength) {
				fillToMax(arow);
			} else {
				return;
			}
		}
	}

		/**
		  * Fill the given row out to the maximum lenght with
		  * "" values.
		*/

	private final void fillToMax(ArrayList al) {
		for (int idx = al.size(); idx < maxlength; idx ++) {
			al.add("");
		}
	}

}
